/**
   \file  stl_utils.hh
   \brief STL helpers.
*/

/*
   This file is part of libgist.

   libgist is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2 of the License, or (at your
   option) any later version.

   libgist is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   for more details.

   You should have received a copy of the GNU General Public License
   along with libgist; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/

/*
   REVISION HISTORY

   $HeadURL: http://libgist.googlecode.com/svn/branches/wu_dev/drv/stl_utils.hh $
   $Id: stl_utils.hh 75 2011-09-29 11:15:19Z libgist@gmail.com $
*/

#ifndef GISTDRV_STL_UTILITIES_DOT_H
#define GISTDRV_STL_UTILITIES_DOT_H

//------------------------------ HEADERS --------------------------------

// Standard C++
#include <algorithm>

//----------------------------- NAMESPACE -------------------------------

namespace gistdrv {

//------------------------- DELETE FUNCTIONS ----------------------------

/**
   \brief Delete object addressed by given pointer.
   \param p Pointer to the object to be deleted.

   This function is useful in conjunction with STL algorithms and
   containers.

   WARNING: P must be a pointer type (e.g., int* rather than int).
*/
template<typename P> void delete_ptr(P p) {delete p ;}

/**
   \brief Delete object pointed to by first element of an STL pair.
   \param p Reference to a pair whose first element is a pointer to a
   dynamically allocated object.

   This function is useful for deleting STL containers of pairs whose
   first elements point to dynamically allocated objects.

   WARNING: Type P \b must be an STL pair and its first member \b must be
   a pointer type (e.g., int* rather than int).
*/
template<typename P> void delete_first (P& p) {delete p.first ;}

/**
   \brief Delete object pointed to by second element of an STL pair.
   \param p Reference to a pair whose second element is a pointer to a
   dynamically allocated object.

   This function is useful for deleting STL containers of pairs whose
   second elements point to dynamically allocated objects.

   WARNING: Type P \b must be an STL pair and its second member \b must
   be a pointer type (e.g., int* rather than int).
*/
template<typename P> void delete_second(P& p) {delete p.second ;}

//------------------------ CONTAINER CLEAN-UP ---------------------------

/**
   \brief Release an STL container of pointers using a specific delete
   function (useful in cases of std::maps).

   \param c The STL container to be purged.
   \param delete_fn A function pointer or object that performs the
   required deletion.

   This function would typically be used to clean-up maps. For example,
   an std::map<int, int*>. In this case, we cannot use delete_ptr<int*>
   directly because the map iterators point to std::pair objects whose
   first member is the key (int in this case) and whose second member is
   the value (int* in this case).

   Thus, we need to supply an appropriate delete function. In this case,
   that function would be delete_second<std::pair<int, int*>>.

   WARNING: Type C \b must be an STL container or \b must provide an
   equivalent begin/end iterator interface.
*/
template<typename C, typename D>
void purge_container(C& c, D delete_fn)
{
   std::for_each(c.begin(), c.end(), delete_fn) ;
}

/**
   \brief Release dynamically allocated objects stored in an STL
   container of pointers.

   \param c The STL container to be purged.

   This function would typically be used to clean-up a containers such as
   std::vector<int*> or other such containers of pointers. In this case,
   value_type would be int*.

   WARNING: Type C \b must be an STL container or provide an equivalent
   begin/end iterator interface and value_type typedef.
*/
template<typename C>
void purge_container(C& c)
{
   typedef typename C::value_type P ;
   purge_container(c, delete_ptr<P>) ;
}

//-----------------------------------------------------------------------

} // end of namespace encapsulating this file's definitions

#endif

/* So things look consistent in everyone's emacs... */
/* Local Variables: */
/* indent-tabs-mode: nil */
/* End: */
